<template>
  <component
    :is="_componentType"
    :file-list="fileList"
    v-bind="$attrs"
    :beforeUpload="beforeUpload"
    @change="handleChange"
    @remove="handleRemove"
    @preview="handlePreview">
    <slot :name="`${_key}-slot`">
      <!-- 拖拽上传默认样式 -->
      <template v-if="_componentType === 'a-upload-dragger'">
        <p class="ant-upload-drag-icon">
          <InboxOutlined />
        </p>
        <p class="ant-upload-text">{{ _placeholder }}</p>
        <p class="ant-upload-hint">
          {{ _hint }}
        </p>
      </template>

      <template v-if="_componentType === 'a-upload'">
        <!-- a-upload picture-card -->
        <div v-if="_listType === 'picture-card'">
          <plus-outlined></plus-outlined>
          <div class="ant-upload-text">{{ _placeholder }}</div>
        </div>
        
        <!-- a-upload 默认样式 -->
        <a-button v-else>
          <upload-outlined></upload-outlined>
          {{ _placeholder }}
        </a-button>
      </template>
    </slot>

    <!-- 照片墙预览 -->
    <a-modal 
      :open="previewVisible" 
      :title="previewTitle" 
      :footer="null" 
      @cancel="handleCancel">
      <img 
        alt="example" 
        style="width: 100%" 
        :src="previewImage" />
    </a-modal>
  </component>
</template>

<script setup>
import { ref, useAttrs } from 'vue'
import { getBase64 } from './util'
import { message } from 'ant-design-vue';
import { 
  InboxOutlined, 
  PlusOutlined, 
  UploadOutlined
} from '@ant-design/icons-vue'

const _$emit = defineEmits(['change', 'update:value', 'preview'])

// $attrs
const $attrs = useAttrs()
// form-item key
const _key = $attrs._key
// 文件列表类型 ('text' | 'picture' | 'picture-card')
const _listType = ref($attrs.listType || 'text')
// 组件类型 ('a-upload' | 'a-upload-dragger')
const _componentType = ref($attrs.type || 'a-upload')
// 主要文案
const _placeholder = ref($attrs.placeholder || '点击上传')
// tip文案
const _hint = ref($attrs.hint || '')

const fileList = ref([])

/**
 * beforeUpload 上传文件之前的钩子
 * @param {File} file 上传的文件
 * @param {File[]} fileList 文件列表
 * @returns {boolean | Promise<any>}
 */
const beforeUpload = (file) => {
  let { maxCount, maxSize, accept, auto } = $attrs

  // 1: maxCount 文件上传数量校验
  // maxCount > 1时校验，ant design 默认值为1，当为 1 时，始终用最新上传的代替当前
  if(maxCount > 1) {
    if(fileList.value.length === maxCount) {
      message.warning({
        right: 0,
        content: `至多选择${maxCount}个文件`,
        maxCount: 5
      })

      return false
    }
  }

  // 2: maxSize 文件大小校验
  if(maxSize) {
    if(file.size > maxSize) {
      message.warning({
        right: 0,
        content: `超出文件大小限制，请重新选择`
      })

      return false
    }
  }

  // 3: accept 文件格式校验
  if(accept) {
    let fileInfo = file.name.split('.');
    let type = fileInfo[fileInfo.length - 1].toLowerCase();

    if(accept.indexOf(type) < 0 || file.type === '') {
      message.warning({
        right: 0,
        content: `${file.name} 文件格式有误，请重新选择`,
        maxCount: 5
      })

      return false;
    }
  }

  // 4: 更新fileList列表
  fileList.value = [...fileList.value, file]
  _$emit('update:value', fileList)
  _$emit('change', fileList)

  // 5: 自动上传校验
  if(auto === false) {
    return false;
  }
}

/**
 * handleChange 文件状态改变时的钩子
 * @param {Object} info 文件对象
 */
const handleChange = (info) => {
  fileList.value = info.fileList
  _$emit('update:value', fileList)
  _$emit('change', fileList)
}

/**
 * handleRemove 删除文件时的钩子
 * @param {*} info 
 */
const handleRemove = (info) => {}

/**
 * 照片墙预览事件 start
 */
const previewVisible = ref(false);
const previewImage = ref('');
const previewTitle = ref('');

const handlePreview = async (file) => {
  _$emit('preview', file)

  // 判断支持默认预览
  let { isPreview } = $attrs
  if(!isPreview) {
    return
  }

  if (!file.url && !file.preview) {
    file.preview = await getBase64(file.originFileObj)
  }

  previewImage.value = file.url || file.preview;
  previewVisible.value = true;
  previewTitle.value = file.name || file.url.substring(file.url.lastIndexOf('/') + 1);
}

const handleCancel = () => {
  previewVisible.value = false;
  previewTitle.value = '';
};
/**
 * 照片墙预览事件 end
 */
</script>

<style scoped lang="less">
</style>